package com.lagou.framework.mvc;

import com.lagou.framework.annotation.Controller;
import com.lagou.framework.annotation.RequestMapping;
import com.lagou.framework.ioc.AnnotationConfigApplicationContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.regex.Pattern;

/**
 * handler 解析器
 *
 * @author srh
 * @date 2020/03/14
 **/
public class HandlerMappingResolver {

    private static Set<MethodHandler> handlerMapping;

    static {
        handlerMapping = new CopyOnWriteArraySet<MethodHandler>();
    }

    public Set<MethodHandler> getHandlerMapping() {
        return handlerMapping;
    }

    public void initHandlerMapping(Map<String, Object> singletonObjects) {
        for (Map.Entry<String, Object> entry : singletonObjects.entrySet()) {
            bindHandlerMethod(entry.getValue());
        }
    }

    private void bindHandlerMethod(Object instance) {
        Class<?> clazz = instance.getClass();
        if (!clazz.isAnnotationPresent(Controller.class)) {
            return;
        }
        String baseUri = "";
        // 拼接类上的uri
        if (clazz.isAnnotationPresent(RequestMapping.class)) {
            RequestMapping classUri = clazz.getAnnotation(RequestMapping.class);
            baseUri = classUri.value();
        }
        // 拼接method上的uri, 如果没有则认为没有要执行的handler
        for (Method method : clazz.getMethods()) {
            if (!method.isAnnotationPresent(RequestMapping.class)) {
                continue;
            }
            RequestMapping methodUri = method.getAnnotation(RequestMapping.class);
            String requestUri = baseUri.concat(methodUri.value());
            Pattern compile = Pattern.compile(requestUri);
            MethodHandler methodHandler = new MethodHandler(instance, method, compile);
            handlerMapping.add(methodHandler);

            Parameter[] parameters = method.getParameters();
            for (int i = 0; i < parameters.length; i++) {
                // 如果是HttpServletRequest或者HttpServletResponse则认为是此名称
                Class<?> parameterType = parameters[i].getType();
                if (parameterType == HttpServletRequest.class || parameterType == HttpServletResponse.class) {
                    methodHandler.getParameterMappings().put(parameterType.getSimpleName(), i);
                } else {
                    methodHandler.getParameterMappings().put(parameters[i].getName(), i);
                }
            }
        }
    }
}
